package com.lhz.project.wage.common;


import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellExtra;
import com.lhz.project.wage.model.excel.WageBaseData;
import com.lhz.project.wage.model.excel.WageWealData;
import com.lhz.project.wage.service.WageService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: LiHuaZhi
 * @Date: 2021/5/1 15:16
 * @Description:
 **/


//有个很重要的点 PersonDataListener 不能被spring管理，要每次读取excel都要new,然后里面用到spring可以构造方法传进去
//每个Listener对应一个导入的Excel格式内容，和对应的Entity
//AnalysisEventListener<T>接收一个泛型 ，可以使用MaP对象进行接收

@Slf4j
@Component
public class WageExcelListener<T> extends AnalysisEventListener<T> {

    @Resource
    private WageService wageService;

    //存放解析后的数据
    private final List<T> list = new ArrayList<>();

    private T t;

    /**
     * 获取额外内容：批注、超链接、合并单元格信息读取，暂时无法测试出效果，并没有进行该方法中，等后续版本更新
     * 注意：2.x以后开始支持
     *
     * @param extra
     * @param context
     */
    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        log.info("读取到了一条额外信息:{}", JSONUtil.toJsonStr(extra));
        switch (extra.getType()) {
            case COMMENT ->
                    log.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(), extra.getText());
            case HYPERLINK -> {
                if ("Sheet1!A1".equals(extra.getText())) {
                    log.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(), extra.getText());
                } else if ("Sheet2!A1".equals(extra.getText())) {
                    log.info("额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}," + "内容是:{}", extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(), extra.getLastColumnIndex(), extra.getText());
                }
            }
            case MERGE ->
                    log.info("合并单元格区域,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}", extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(), extra.getLastColumnIndex());
            default -> {
            }
        }
    }

    /**
     * 读取每一条头部信息
     *
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        log.info("解析到一条头数据:{}", JSONUtil.toJsonStr(headMap));
    }


    /**
     * 这个每一条数据解析都会来调用
     *
     * @param t       one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(T t, AnalysisContext context) {
        this.t = t;
        log.info("解析到一条数据:{}", JSONUtil.toJsonStr(t));
        //调用service类进行一些业务判断操作
        Integer rowIndex = context.readRowHolder().getRowIndex() + 1;//当时行数，从0开始，实际加1
        //通过判断泛型类，调用不同的Service类
        if (t instanceof WageBaseData) {
            WageBaseData data = (WageBaseData) t;
            wageService.checkBaseExcel(data, rowIndex);
            list.add(t);
        }

        if (t instanceof WageWealData) {
            WageWealData data = (WageWealData) t;
            wageService.checkWealExcel(data, rowIndex);
            list.add(t);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成！");
    }

    /*
     * 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
     *
     * @param exception
     * @param context
     * @throws Exception

     @Override public void onException(Exception exception, AnalysisContext context) {
     log.error("解析失败，但是继续解析下一行:{}", exception.getMessage());

     // 如果是某一个单元格的转换异常 能获取到具体行号
     // 如果要获取头的信息 配合invokeHeadMap使用
     if (exception instanceof ExcelDataConvertException) {
     ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
     log.error("第{}行，第{}列解析异常", excelDataConvertException.getRowIndex(),
     excelDataConvertException.getColumnIndex());
     }
     }
     */

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据，开始存储数据库！", list.size());

        //人员数据
        if (t instanceof WageBaseData) {
            String jsonString = JSONUtil.toJsonStr(list);
            List<WageBaseData> dataList = JSONUtil.toList(jsonString, WageBaseData.class);
            list.clear();
            wageService.saveBaseExcel(dataList);
        }

        //设备数据
        if (t instanceof WageWealData) {
            String jsonString = JSONUtil.toJsonStr(list);
            List<WageWealData> dataList = JSONUtil.toList(jsonString, WageWealData.class);
            list.clear();
            wageService.saveWealExcel(dataList);
        }
    }
}